﻿using System;
using System.Diagnostics.Contracts;
using Microsoft.Practices.ServiceLocation;

namespace Beaker.Injection
{

	/// <summary>
	/// Allows external DI Frameworks to be plugged in
	/// </summary>
	[ContractClass(typeof(InjectionProviderContracts))]
	public interface IInjectionProvider
	{
		/// <summary>
		/// Create the container builder the modules will be using to register there types.
		/// </summary>
		IContainerBuilder CreateContainerBuilder();

		/// <summary>
		/// Register the given MEF container, so entities exported using MEF will work with DI.
		/// </summary>
		/// <param name="builder">The builder to register the MEF container with.</param>
		/// <param name="locator">The orignal service locator configured before we replaced it.</param>
		void RegisterServiceLocator(IContainerBuilder builder, IServiceLocator locator);

		/// <summary>
		/// Register the IFactory{TService} interface so it will work to build defered instances.
		/// </summary>
		/// <param name="builder">The builder to register the Factory interface with.</param>
		void RegisterFactory(IContainerBuilder builder);

		/// <summary>
		/// Build the IQueryContainer, add it to itself, then lock it and return it.
		/// </summary>
		/// <param name="builder">The builder to Build into a IQueryContainer and Lock.</param>
		/// <param name="skipVerify">set to true, when user requested to skip verify phase.</param>
		/// <returns>The build query container.</returns>
		IQueryContainer BuildAndLock(IContainerBuilder builder, bool skipVerify);
	}

	/// <summary>
	/// Code Contracts for the <see cref="IInjectionProvider"/> interface.
	/// </summary>
	[ContractClassFor(typeof(IInjectionProvider))]
	abstract class InjectionProviderContracts
		: IInjectionProvider
	{
		public IContainerBuilder CreateContainerBuilder()
		{
			Contract.Ensures(Contract.Result<IContainerBuilder>() != null);
			throw new NotImplementedException();
		}

		public void RegisterServiceLocator(IContainerBuilder builder, IServiceLocator locator)
		{
			Contract.Requires<ArgumentNullException>(builder != null);
			Contract.Requires<ArgumentNullException>(locator != null);
			throw new NotImplementedException();
		}

		public void RegisterFactory(IContainerBuilder builder)
		{
			Contract.Requires<ArgumentNullException>(builder != null);
			throw new NotImplementedException();
		}

		public IQueryContainer BuildAndLock(IContainerBuilder builder, bool skipVerify)
		{
			Contract.Requires<ArgumentNullException>(builder != null, "builder");
			Contract.Ensures(Contract.Result<IQueryContainer>() != null);
			throw new NotImplementedException();
		}
	}

}
